<?php

namespace App\Recharge\Service;

use App\Jobs\OrderCallbackNotify;
use App\Models\NsSupplierGoods;
use App\Models\XnBatchOrder;
use App\Models\XnMyyGoodsInterconnection;
use App\Recharge\Enums\ApiGroupEnum;
use App\Recharge\Exceptions\CyclePunch\MainProductNotFoundException;
use App\Recharge\Exceptions\CyclePunch\MerchantIsNotFoundException;
use App\Recharge\Exceptions\CyclePunch\MerchantPriceWithTicketNotSetException;
use App\Recharge\Library;
use App\Recharge\Logic\GoodLogic;
use App\Recharge\Logic\CycleLogic;
use App\Recharge\Logic\ConfigLogic;
use App\Recharge\Bean\CyclePunchBean;
use App\Recharge\Traits\RechargeTraits;
use App\Recharge\Exceptions\SuspensionOfEnforcement;


abstract class BaseService
{
   use RechargeTraits;

    /**
     * @var CycleLogic 逻辑层
     */
    protected CycleLogic $logic;

    /**
     * @var ConfigLogic 配置逻辑层
     */
    protected ConfigLogic $cg;

    /**
     * @var GoodLogic
     */
    protected GoodLogic $goodLogic;

    /**
     * @var CyclePunchBean
     */
    protected CyclePunchBean $bean;

    /**
     * @var ApiGroupEnum
     */
    protected ApiGroupEnum $apiGroup;

    /**
     * 初始化
     *
     * @param XnBatchOrder $order 订单
     */
    public function __construct(public XnBatchOrder $order)
    {
        $this->cg = new ConfigLogic();
        $this->logic = new CycleLogic();
        $this->goodLogic = new GoodLogic();
        // 获取enums
        $this->apiGroup = ApiGroupEnum::identify($this->order->Supplier_status);
        // bean
        $this->bean = new CyclePunchBean();
        $this->bean->setOrder($this->order);
        $this->bean->setOrderNo($this->apiGroup->order_sn($this->order->orderNum));
    }

    /**
     * 创建
     *
     * @param XnBatchOrder $order 订单
     * @return static
     */
    public static function new(XnBatchOrder $order): static
    {
        return new static($order);
    }

    /**
     * 执行方法
     *
     * @return void
     */
    abstract public function execute(): void;

    /**
     * 主商品
     *
     * @return void
     * @throws MainProductNotFoundException
     * @throws MerchantIsNotFoundException
     * @throws MerchantPriceWithTicketNotSetException
     */
    protected function mainGood(): void
    {
//        $good = NsSupplierGoods::query()->find($this->order->goodsId);
        $good = XnMyyGoodsInterconnection::query()->find($this->order->goodsId);
        if (!$good) {
            throw new MainProductNotFoundException();
        }
        // 是否是带票的
        if ($this->order->is_tax == 1) {
            goto end;
        }
        // 结束判断
        end:
        {
            $this->bean->setGood($good);
            // 判断是否上架
//            if ($good->release != 1) {
            if ($good->status != 1) {
                throw new MainProductNotFoundException("商品未上架");
            }
        }
    }

    /**
     * 电信过滤
     *
     * @param array $child
     * @return bool
     * @throws SuspensionOfEnforcement
     */
    protected function telecomFiltering(array $child): bool
    {
        $telecom_open = $child['telecom_open'] ?? 2;
        if ($telecom_open != 1) {
            return true;
        }
        // 记录日志
        $errorMessage = '子商品开启了电信过滤,当前手机号归属不是电信';
        // 检测是否是电信的
        $is = $this->bean->getPhoneIsTelecom();
        if (!is_null($is)) {
            goto end;
        }
        if (!isPhone($this->order->userName)) {
            throw new SuspensionOfEnforcement($errorMessage . ',也不是手机号');
        }
        $belong = $this->bean->getPhoneBelong();
        if (is_null($belong)) {
            $belong = Library::mobilePhoneLocationInquiry($this->order->userName);
            $this->bean->setPhoneBelong($belong);
            if (!$belong) {
                throw new SuspensionOfEnforcement($errorMessage . ',第三方查询为空');
            }
        }
        $is = str_contains($belong, '电信');
        $this->bean->setPhoneIsTelecom($is);
        end: return $is == true || throw new SuspensionOfEnforcement($errorMessage);
    }


    /**
     * 全部失败逻辑
     *
     * @param string $errorMessage
     * @return void
     */
    protected function allOrdersFailed(string $errorMessage = '下单失败'): void
    {
        OrderCallbackNotify::dispatch($this->order, false, $errorMessage)->onQueue('h5_notify');
    }
}
